基本觀念的最後一個部分,Operator
,就像是物件導向的不同部分有不同的變形一樣,Operator 在 Combine 中扮演了舉足輕重的角色,沒有了他,Combine 只是 if then
。
Operator 可以區分為一下大類
轉換類型 map, scan, flapMap
一般篩選類型 compactMap, filter, removeDuplicates
整併類型 reduce, collect
運算類型 count, comparison
符合篩選類型 contains, allSatisfy
序列篩選類型 first, last, drop, firstWhere,
上流整合類型 zip, merge, combineLatest
型別銜接類型 eraseToAnyPublisher, switchToLatest
失敗處理類型 catch, retry, mapError
時間控制類型 debounce, throttle, delay, timeout
格式解析類型 Encode, decode
Debugging類型 print, breakpoint, handleEvents
因版面關係,略過錯誤情形,例如
tryMap
, 詳細請參考 Publishers namespace
接下來會依序介紹 Operator,配合 Marbles diagram,介紹Operator。
讓我想到
Array.map
,若以這個角度來看是像的。
func map<T>(_ transform: @escaping (Self.Output) -> T) -> Publishers.Map<Self, T>
transform: 元素映射閉包, 帶入上游元素,回傳新元素。
Return Value
Publisher 使用上游提供的元素映射閉包, 並套用於隨後發布的新元素。
******demo code*******
Just("1")
.map(atof)
.dprint()
.sink{_ in}
******console*********
FILETests.swift 1: receive subscription: (Just)
FILETests.swift 1: request unlimited
FILETests.swift 1: receive value: (1)
FILETests.swift 1: receive finished
*******Rarbles********
------("1")------|
map(atof)
------(1.0)------|
讓我想到
Array.reduce
,若以這個角度來看很清楚。
func scan<T>(_ initialResult: T, _ nextPartialResult: @escaping (T, Self.Output) -> T) -> Publishers.Scan<Self, T>
Parameters
initialResult
初試值,同時確定 return Publisher.Output
nextPartialResult
元素映射閉包,附帶兩個帶出參數,分別是
A closure that takes as its arguments the previous value returned by the closure and the next element emitted from the upstream publisher.
*****demo code*******
[1,0,3].publisher
.dprint() // ? before
.scan(0){max($0,$1)}
.dprint() // ? after
.sink{_ in}
*****console*********
FILETests.swift ?: receive subscription: ([1, 0, 3])
FILETests.swift ?: receive subscription: (Print)
FILETests.swift ?: request unlimited
FILETests.swift ?: request unlimited
FILETests.swift ?: receive value: (1)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive value: (3)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive finished
FILETests.swift ?: receive finished
*******Rarbles*******
-1--------0---------3-|
scan(0){max($0,$1)}
-1--------1---------3-|
(試解釋)將上流的事件以延伸流的方式執行邏輯處理,吧
p.s. 據說這是最難懂的!老實說筆者在寫的時候還沒搞懂,
func flatMap<T, P>(maxPublishers: Subscribers.Demand = .unlimited, _ transform: @escaping (Self.Output) -> P) -> Publishers.FlatMap<P, Self> where T == P.Output, P : Publisher, Self.Failure == P.Failure
Parameters
maxPublishers
//The maximum number of publishers produced by this method.
transform
//A closure that takes an element as a parameter and returns a publisher that produces elements of that type.
Return Value
//A publisher that transforms elements from an upstream publisher into a publisher of that element’s type.
Discussion
flatMap merges the output from all returned publishers into a single stream of output.
******demo code*******
_ = [
"1.2".data(using: .utf8)!,
"1".data(using: .utf8)!
].publisher
.flatMap{
return Just($0)
.decode(type: Int.self, decoder: JSONDecoder())
.catch{_ in return Just(0)}
}
.dprint()
.sink{_ in}
******console*********
FILETests.swift 1: receive subscription: (FlatMap)
FILETests.swift 1: request unlimited
FILETests.swift 1: receive value: (0)
FILETests.swift 1: receive value: (1)
FILETests.swift 1: receive finished
*******Rarbles********
---"1.2"----------"1"|
flatMap
+Decode +Decode
----X ----1
+catch
0|
------0------------------1|
有趣的是,我嘗試使用 .map{}.switchtoLast()
也可以得到結果!所以 flatMap
是這個的化簡嗎? ?
簡單測驗:
Publishers.FlatMap
與 Array.flatMap
(other language's compactMap) 差別whoami:
我是游諭 ytyubox